package com.uraurora.crescent.tuple;

import com.google.common.collect.Iterables;
import com.uraurora.crescent.util.SeiIterables;

import java.util.Objects;

/**
 * 通用的不可变元组类，作用等同于python的tuple，与诸如Tuple1,Tuple2等类的区别是无法指定索引的类型,
 * 但是可以创建更多元素的元组对象
 * <p>创建方法是静态工厂{@code of}方法，不提供公有的构造器，原因是减少可变性并且不允许子类继承的行为
 * @author gaoxiaodong
 */
public class Tuple extends AbstractTuple implements ITuple {

    private Tuple(Object[] values) {
        super(values);
    }

    private Tuple(Iterable<?> iterable){
        super(SeiIterables.toArray(iterable, Iterables.size(Objects.requireNonNull(iterable))));
    }

    public static Tuple of(Iterable<?> iterable){
        return new Tuple(iterable);
    }

    public static Tuple of(Object[] objects){
        return new Tuple(objects);
    }

    public static Tuple of(Object o){
        return new Tuple(new Object[]{o});
    }

    public static Tuple of(Object o1, Object o2){
        return new Tuple(new Object[]{o1, o2});
    }

    public static Tuple of(Object o1, Object o2, Object o3){
        return new Tuple(new Object[]{o1, o2, o3});
    }

    public static Tuple of(Object o1, Object o2, Object o3, Object o4){
        return new Tuple(new Object[]{o1, o2, o3, o4});
    }

    public static Tuple of(Object o1, Object o2, Object o3, Object o4, Object o5){
        return new Tuple(new Object[]{o1, o2, o3, o4, o5});
    }

    public static Tuple of(Object o1, Object o2, Object o3, Object o4, Object o5, Object... others){
        Object[] objects = new Object[others.length+5];
        objects[0] = o1; objects[1] = o2; objects[2] = o3; objects[3] = o4; objects[4] = o5;
        System.arraycopy(others, 0, objects, 5, others.length);
        return new Tuple(objects);
    }
}
